package redis

import (
	"context"
	"errors"
	"strconv"
	"time"

	"github.com/go-redis/redis/v8"
)

const (
	oneWeekInSeconds = 7 * 24 * 60 * 60
	scorePerVote     = 432
)

var (
	ErrVoteTimeExpire = errors.New("投票时间已过")
)

func CreatePost(postID int64, communityID int64) error {
	ctx := context.Background()
	pipeline := client.Pipeline()
	// 帖子时间
	pipeline.ZAdd(ctx, getRedisKey(KeyPostTime), &redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: postID,
	})

	// 帖子分数
	pipeline.ZAdd(ctx, getRedisKey(KeyPostScore), &redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: postID,
	})

	// 更新：把帖子id加到社区的set
	cKey := getRedisKey(KeyCommunitySetPf + strconv.Itoa(int(communityID)))
	pipeline.SAdd(ctx, cKey, postID)
	_, err := pipeline.Exec(ctx)

	return err
}

func VoteForPost(userID, postID string, value float64) error {
	ctx := context.Background()
	// 1.判断投票限制
	// 去redis取帖子发布时间
	postTime := client.ZScore(ctx, getRedisKey(KeyPostTime), postID).Val()
	if float64(time.Now().Unix())-postTime > oneWeekInSeconds {
		return ErrVoteTimeExpire
	}

	// 2.更新帖子的分数
	// 先查当前用户给当前帖子的投票记录
	ov := client.ZScore(ctx, getRedisKey(KeyPostVotedPf+postID), userID).Val()
	//var op float64
	//if value > ov {
	//	op = 1
	//} else {
	//	op = -1
	//}
	//diff := math.Abs(ov - value)
	// 更新操作需要放到一个pipeline事务中操作
	pipeline := client.TxPipeline()
	pipeline.ZIncrBy(ctx, getRedisKey(KeyPostScore), (value-ov)*scorePerVote, postID)
	// 3.记录用户为该帖子投票的数据
	if value == 0 {
		pipeline.ZRem(ctx, getRedisKey(KeyPostVotedPf+postID), userID)
	} else {
		pipeline.ZAdd(ctx, getRedisKey(KeyPostVotedPf+postID), &redis.Z{
			Score:  value,
			Member: userID,
		})
	}

	_, err := pipeline.Exec(ctx)
	return err
}
